
/**
  ******************************************************************************
  * Copyright 2021 The grapilot Authors. All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  * 
  * @file       gp_quat.h
  * @author     baiyang
  * @date       2021-7-6
  ******************************************************************************
  */

#pragma once

#ifdef __cplusplus
extern "C"{
#endif

/*----------------------------------include-----------------------------------*/
#include <math.h>
#include "gp_vector3.h"
/*-----------------------------------macro------------------------------------*/
#define QUAT_DEFAULT_VALUE {1.0f, 0.0f, 0.0f, 0.0f}
#define EULER_DEFAULT_VALUE {0.0f, 0.0f, 0.0f}
/*----------------------------------typedef-----------------------------------*/
typedef union
{
    struct
    {
        float w;
        float x;
        float y;
        float z;
    };
    struct
    {
        float q0;
        float q1;
        float q2;
        float q3;
    };
    float vec[4];
}Quat_t;

typedef union
{
    struct
    {
        float x;
        float y;
        float z;
    };

    struct
    {
        float roll;
        float pitch;
        float yaw;
    };

    float vec[3];
}Euler_t;

/*----------------------------------variable----------------------------------*/

/*-------------------------------------os-------------------------------------*/

/*----------------------------------function----------------------------------*/
void quat_init(Quat_t* q);

float quat_length(const Quat_t* q);
void quat_norm(Quat_t* q);

void quat_inverse(Quat_t* qout, const Quat_t* qin);
Quat_t quat_inverse2(const Quat_t* qin);
void quat_invert(Quat_t* q);

Quat_t quat_mult(const Quat_t* left, const Quat_t* right);
Quat_t quat_mult2(const Quat_t* left, const Quat_t* middle, const Quat_t* right);

void quat_add(Quat_t* q, const Quat_t* left, const Quat_t* right);

void quat_from_euler(Quat_t* q, const float roll, const float pitch, const float yaw);
void quat_to_euler(const Quat_t* q, Euler_t* euler);

float quat_get_roll(const Quat_t* q);
float quat_get_pitch(const Quat_t* q);
float quat_get_yaw(const Quat_t* q);

void quat_from_axis_angle1(Quat_t* q, const Vector3f_t* v);
void quat_from_axis_angle2(Quat_t* q, const Vector3f_t* axis, const float theta);
void quat_to_axis_angle(const Quat_t* q, Vector3f_t* v);

void quat_from_axis_angle_fast1(Quat_t* q, const Vector3f_t* v);
void quat_from_axis_angle_fast2(Quat_t* q, const Vector3f_t* axis, const float theta);

void quat_rotate(Quat_t* q, const Vector3f_t* v);
void quat_rotate_fast(Quat_t* q, const Vector3f_t* v);

void quat_vec_rotate(const Quat_t* q, Vector3f_t* v_d, const Vector3f_t* v_s);
void  quat_inv_vec_rotate(const Quat_t* q, Vector3f_t* v_d, const Vector3f_t* v_s);

/*------------------------------------test------------------------------------*/

#ifdef __cplusplus
}
#endif



